﻿#include <glog/logging.h>
#include <QFile>
#include <QDateTime>
#include <vector>

#include "constant.h"
#include "util/utils.h"
#include "manager/camera_manager.h"
#include "manager/mqtt_manager.h"
#include "manager/algorithm_manager.h"
#include "manager/config_manager.h"
#include "detect/result_manager.h"

CameraManager::CameraManager()
{
    cmd_status = IDLE;
    connect(&camera, SIGNAL(image_ready(QSharedPointer<Mat>)), this, SLOT(on_image(QSharedPointer<Mat>)));
}

CameraManager *CameraManager::get_instance() {
    static CameraManager instance;
    return &instance;
}

bool CameraManager::init() {
    AppConfig *app_config = ConfigManager::getInstance()->get_app_config();
    QString rtsp_camera = app_config->rtsp_camera;
    QByteArray arr_rtsp_camera = rtsp_camera.toLocal8Bit();
    return camera.open(arr_rtsp_camera.constData());
}

void CameraManager::start() {
    if (camera.is_cam_open() == false) {
        init();
    }
    time = QTime::currentTime();
    time.start();
    camera.start_grab();
}

void CameraManager::stop() {
}

void CameraManager::do_cmd(CommandEntity cmd) {
    if (cmd_status == START || cmd_status == RECORD) {
        LOG(INFO) << "CameraManager | do_cmd | busy!!!!";
        return;
    }
    this->cmd = cmd;
    cmd_status = START;
    LOG(INFO) << "CameraManager | do_cmd | cmd.type" << cmd.type.toStdString();
}

void CameraManager::on_image(QSharedPointer<Mat> sp_frame) {
    // LOG(INFO) << "CameraManager | on_image | ellapse" << time.elapsed();
    AppConfig *ptr_app_config = ConfigManager::getInstance()->get_app_config();
    if (ptr_app_config->algorithm_type == ALGORITHM_TYPE_VECHICLE_PEDESTRIAN) {
        // 车辆行人检测系统仅进行识别
        if (time.elapsed() > ALGORITHM_VEHICLE_DETECT_DURATION_MS) {
             AlgorithmManager::get_instance()->detect(sp_frame);
             time.restart();
        }
    } else {
        // 行人检测系统需要进行kcf跟踪
        if (time.elapsed() > ALGORITHM_DETECT_DURATION_MS) {
            ResultManager::get_instance()->update_buffer_kcf_async(sp_frame, true);
            AlgorithmManager::get_instance()->detect(sp_frame);
            time.restart();
        } else {
            ResultManager::get_instance()->update_buffer_kcf_async(sp_frame, false);
        }
    }
    ConfigEntity *config = ConfigManager::getInstance()->get_ecb_config();
    QString video_resolution = config->video_resolution;

    int x_width = video_resolution.section('x', 0, 0).toInt();
    int y_height = video_resolution.section('x', 1, 1).toInt();
    // LOG(INFO) << "on_image | video_resolution" << video_resolution << "x" << x_width << "y" << y_height;
    if (cmd_status == START) {
        if (this->cmd.type == "picture") {
            std::vector<uchar> result = Utils::mat_to_image(sp_frame, config->picture_format);
            int size = result.size();
            char *bytes = new char[size];
            for (int i = 0; i < size; ++i) {
                bytes[i] = result[i];
            }
            MqttManager::getInstance()->send_picture(bytes, size);
            delete []bytes;
            cmd_status = IDLE;
        }

        if (this->cmd.type == "video") {
            QFile::remove(VIDEO_FILE);
            LOG(INFO) << "CameraManager | on_image | start record video x" << x_width << "y" << y_height;
            video_writer.open(VIDEO_FILE, CV_FOURCC('D', 'I', 'V', 'X'), 12, cv::Size(x_width, y_height));
            if (!video_writer.isOpened()) {
                LOG(INFO) << "CameraManager | on_image | open video file failed";
                cmd_status = IDLE;
                return;
            }
            cmd_status = RECORD;
            record_start_time = QDateTime::currentDateTime().toTime_t();
        }
    }

    if (cmd_status == RECORD) {
        uint current_time = QDateTime::currentDateTime().toTime_t();
        if (current_time - record_start_time <= cmd.length) {
            LOG(INFO) << "CameraManager | on_image | record length"
                     << current_time - record_start_time << "total" << cmd.length;
            Mat dst = Mat::zeros(x_width, y_height, CV_8UC3);
            cv::resize(*sp_frame, dst, dst.size());
            video_writer << dst;
        } else {
            LOG(INFO) << "CameraManager | on_image | record finish";
            video_writer.release();
            record_start_time = 0;
            cmd_status = IDLE;
            MqttManager::getInstance()->send_video_file();
        }
    }
}
